import json
import re
from django.shortcuts import render
from django.views import View
from django import http
from django_redis import get_redis_connection

from apps.users.models import User
from libs.captcha.captcha import captcha
from libs.yuntongxun.sms import CCP
from meiduo_mall.settings.dev import LOGGER
import random
from utils.response_code import RETCODE
from utils.secret import SecretOauth
from . import constants
from celery_tasks.sms.tasks import send_sms_code

# Create your views here.


class ImageCountView(View):
    """验证码 生成"""
    def get(self, request, uuid):

        # 产生验证码
        capt_code, image = captcha.generate_captcha()

        # 连接验证码缓存数据库
        redis_cli = get_redis_connection("captcha")

        # 验证码数据设置过期时间并写入缓存数据库
        redis_cli.setex("img_%s" % uuid, constants.IMAGE_CODE_REDIS_EXPIRE, capt_code)
        # print("写入:{}".format("img_%s" % uuid))
        # 响应图片验证码
        return http.HttpResponse(image, content_type='image/jpeg')


class SMSCodeView(View):
    def get(self, request, mobile):
        # 前端接口:
        # www.meiduo.site/sms_codes/mobile/?image_code=image_code&image_code_id=image_code_id
        mobile = mobile
        image_code = request.GET.get('image_code')
        image_code_id = request.GET.get('image_code_id')
        # 查询 captcha 数据库
        img_cli = get_redis_connection("captcha")
        redis_img_code = img_cli.get("img_%s" % image_code_id)  # "img_%s" % uuid

        # 判断服务器返回的验证
        if redis_img_code is None:
            return http.JsonResponse({'code': "4001", 'errmsg': '图形验证码失效'})

        # 存在删除 数据库操作必定捕获异常
        try:
            img_cli.delete("img_%s" % image_code_id)
        except Exception as e:
            LOGGER.error(e)

        # 与用户输入进行比较
        if image_code.lower() != redis_img_code.decode().lower():
            return http.JsonResponse({'code': "4001", 'errmsg': '图形验证码错误'})

        # 图形验证码验证正确　生成随机短信验证码
        sms_code = "%06d" % random.randint(0, 100000)
        sms_cli = get_redis_connection("sms_code")

        # 短信屏蔽频繁
        send_flag = sms_cli.get("send_flag_%s" % mobile)

        if send_flag:
            return http.JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '发送短信过于频繁'})

        # 创建管道
        sms_pip = sms_cli.pipeline()
        sms_pip.setex("sms_code_%s" % mobile, constants.SMS_CODE_REDIS_EXPIRE, sms_code)
        sms_pip.setex("send_flag_%s" % mobile, constants.SEND_SMS_CODE_EXPIRE, 1)
        sms_pip.execute()

        # 正常处理短信验证码发送
        # CCP().send_template_sms(mobile, [sms_code, 5], 1)
        # print("将要发送的验证码是:{}".format(sms_code))

        # 异步发送短信任务
        send_sms_code.delay(mobile, sms_code)
        return http.JsonResponse({'code': '0', 'errmsg': '发送短信成功'})


class AccountVerifyView(View):
    def get(self, request, username):
        """[忘记密码]账号校验"""
        uuid = request.GET.get('image_code_id')
        image_code = request.GET.get('text')

        # 验证码有效性判断
        img_cli = get_redis_connection("captcha")
        img_redis = img_cli.get("img_%s" % uuid)
        if img_redis is None:
            return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码已过期，点击图片换一个'})
        # 随取随删
        img_cli.delete("img_%s" % uuid)

        # 判断验证码输入是否正确
        if img_redis.decode().lower() != image_code.lower():
            return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码错误'}, status=400)
        # 参数校验
        if not re.match(r"^[a-zA-Z0-9_-]{5,20}$", username):
            return http.JsonResponse({'code': RETCODE.NODATAERR, 'errmsg': '用户名不合法'})
        # if username.isdigit() and len(username) == 11:
        #     try:
        #         user = User.objects.get(mobile=username)
        #     except Exception as e:
        #         LOGGER.error(e)
        #         return http.JsonResponse({}, status=404)
        # else:
        #     try:
        #         user = User.objects.get(username=username)
        #     except Exception as e:
        #         LOGGER.error(e)
        #         return http.JsonResponse({}, status=404)
        try:
            user = User.objects.get(username=username)
        except Exception as e:
            LOGGER.error(e)
            return http.JsonResponse({}, status=404)
        # 构造前端返回数据
        json_str = SecretOauth().dumps({"user_id": user.id, 'mobile': user.mobile})
        return http.JsonResponse({'mobile': user.mobile, 'access_token': json_str})


class SendSMSToMobileView(View):
    """[忘记密码] 短信校验"""
    def get(self, request):
        access_token = request.GET.get('access_token')
        # 解密
        user_data = SecretOauth().loads(access_token)
        if user_data is None:
            return http.JsonResponse({}, status=400)
        mobile = user_data["mobile"]
        try:
            User.objects.get(mobile=mobile)
        except:
            return http.JsonResponse({}, status=400)

        sms_cli = get_redis_connection("sms_code")
        # 短信屏蔽频繁
        send_flag = sms_cli.get("send_flag_%s" % mobile)

        if send_flag is not None:
            return http.JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '发送短信过于频繁'})
        # 六位验证码随机生成
        sms_code = "%06d" % random.randint(0, 100000)
        # 创建管道
        sms_pip = sms_cli.pipeline()
        sms_pip.setex("sms_code_%s" % mobile, constants.SMS_CODE_REDIS_EXPIRE, sms_code)
        sms_pip.setex("send_flag_%s" % mobile, constants.SEND_SMS_CODE_EXPIRE, 1)
        sms_pip.execute()

        # 异步发送短信任务
        # send_sms_code.delay(mobile, sms_code)
        print("手机号：{},验证码：{}".format(mobile, sms_code))

        return http.JsonResponse({"message": "ok"})


class SMSVerifyView(View):
    def get(self, request, username):
        sms_code = request.GET.get("sms_code")
        sms_cli = get_redis_connection("sms_code")
        try:
            user = User.objects.get(username=username)
        except Exception as e:
            LOGGER.error(e)
            return http.JsonResponse({}, status=400)
        mobile = user.mobile
        redis_sms = sms_cli.get("sms_code_%s" % mobile)
        if redis_sms is None:
            return http.HttpResponseForbidden('短信验证码已经过期')
        # 随取随删
        sms_cli.delete("sms_code_%s" % mobile)
        sms_cli.delete("send_flag_%s" % mobile)

        if redis_sms.decode() != sms_code:
            return http.HttpResponseForbidden('短信验证码错误')
            # return http.JsonResponse({'code': RETCODE.SMSCODERR, 'message': '短信验证码错误'})
        json_str = SecretOauth().dumps({"user_id": user.id, 'mobile': user.mobile})
        return http.JsonResponse({'user_id': user.id, 'access_token': json_str})

class SencondPasswordView(View):
    def post(self, request, user_id):
        """重置密码提交"""
        data_dict = json.loads(request.body.decode())
        pwd = data_dict.get("password")
        cpwd = data_dict.get("password2")
        access_token = data_dict.get('access_token')
        # 密码参数校验
        if not re.match(r"^[0-9A-Za-z]{8,20}$", pwd):
            return http.HttpResponseForbidden("密码不合法啊!")
        if not all([access_token, pwd, cpwd]):
            return http.HttpResponseForbidden('填写数据不完整')
        if pwd != cpwd:
            return http.HttpResponseForbidden("两次密码不一致!")
        user_dict = SecretOauth().loads(access_token)
        if user_dict is None:
            return http.JsonResponse({}, status=400)
        # 用户id校验
        if int(user_id) != user_dict['user_id']:
            return http.JsonResponse({}, status=400)
        try:
            user = User.objects.get(id=user_id)
        except Exception as e:
            LOGGER.error(e)
            return http.JsonResponse({}, status=400)

        # 修改密码
        user.set_password(cpwd)
        user.save()
        return http.JsonResponse({})